package middleware

import (
	"bytes"
	"fmt"
	"log/slog"
	"strings"

	"gitee.com/jiebaiyou/formflow/internal/tokenutil"
	"gitee.com/jiebaiyou/formflow/pkg/response"
	"github.com/gin-gonic/gin"
)

// JwtAuth 验证中间件
func JwtAuth(secret string) gin.HandlerFunc {
	return func(c *gin.Context) {
		var (
			authorization string
			namespace     string
			aud           string
		)

		// 第一种情况: 正常的HTTP请求, 使用header中"authorization"参数
		// 第二种情况: WebSocket请求使用ws子协议中"sec-websocket-protocol"参数
		// 第三种情况: 兼容前端H5原生WebSocket请求, 使用url中"token"参数
		params := []string{"token", "authorization", "sec-websocket-protocol"}
		for _, param := range params {
			authorization = getParam(c, param)
			if len(authorization) != 0 {
				break
			}
		}

		authorization = strings.TrimPrefix(authorization, "Bearer ")
		namespace = strings.ReplaceAll(getParam(c, "namespace"), ".", "-")
		aud = getParam(c, "aud")

		// 检查参数是否为空
		if isEmpty(namespace, aud, authorization) {
			slog.Error("验证Token失败", slog.String("error", "authorization, namespace, aud is required"))
			response.BadRequest(c, "验证Token失败", "authorization, namespace, aud is required")
			c.Abort()
			return
		}

		// 从Etcd中获取客户Secret配置
		// secret, err := cache.GetCache(namespace)
		// if err != nil {
		// 	slog.Error("验证Token失败", slog.String("error", err.Error()))
		//  response.BadRequest(c, "验证Token失败", err)
		// 	c.Abort()
		// 	return
		// }

		// 验证Token
		customClaims, err := tokenutil.IsAuthorized(authorization, secret)
		if err != nil {
			slog.Error("验证Token失败", slog.String("error", err.Error()), slog.String("namespace", namespace), slog.String("secret", secret))
			response.BadRequest(c, "验证Token失败", err)
			c.Abort()
			return
		}

		// 验证namespace, aud和Token中的是否一致
		// customClaims.Namespace = strings.ReplaceAll(customClaims.Namespace, ".", "-")
		// if customClaims.Namespace != namespace || customClaims.Audience != aud {
		// 	slog.Error("验证Token失败", slog.String("error", "namespace or aud is invalid"))
		// 	response.BadRequest(c, "验证Token失败", "namespace or aud is invalid")
		// 	c.Abort()
		// 	return
		// }

		var buffer bytes.Buffer
		buffer.WriteString(strings.Repeat("-", 17) + " JWT Middleware " + strings.Repeat("-", 17) + "\n")
		buffer.WriteString(fmt.Sprintf("%-15s %s\n", "authorization:", authorization))
		// buffer.WriteString(fmt.Sprintf("%-15s %s\n", "namespace:", customClaims.Namespace))
		// buffer.WriteString(fmt.Sprintf("%-15s %s\n", "audidence:", customClaims.Audience))
		// buffer.WriteString(fmt.Sprintf("%-15s %s\n", "issuer:", customClaims.Issuer))
		// buffer.WriteString(fmt.Sprintf("%-15s %s\n", "subject:", customClaims.Subject))
		// buffer.WriteString(fmt.Sprintf("%-15s %d\n", "user_id:", customClaims.Params.UserID))
		// buffer.WriteString(fmt.Sprintf("%-15s %s\n", "user_name:", customClaims.Params.UserName))
		buffer.WriteString(fmt.Sprintln(strings.Repeat("-", 50)))
		fmt.Println(buffer.String())

		c.Set("customClaims", customClaims)

		c.Next()
	}
}

// 获取请求参数
func getParam(ctx *gin.Context, name string) string {
	value := ctx.Query(name)
	if len(value) == 0 {
		value = ctx.Request.Header.Get(name)
	}
	return value
}

// 检查参数是否为空
func isEmpty(params ...any) bool {
	for _, param := range params {
		switch v := param.(type) {
		case string:
			if len(v) == 0 {
				return true
			}
		case bool:
			if !v {
				return true
			}
		}
	}
	return false
}
